package cn.cht.sqlsession;

import cn.cht.pojo.Configuration;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

public class DefaultSqlSession implements SqlSession {

    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementid, Object... params) throws Exception {
        //将要去完成对simpleExecutor里的query方法的调用
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        List<Object> list = simpleExecutor.query(configuration, configuration.getMap().get(statementid), params);
        return (List<E>) list;
    }

    @Override
    public <T> T selectOne(String statementid, Object... params) throws Exception {
        List<Object> objects = selectList(statementid, params);
        if (objects.size() ==1) {
            return (T) objects.get(0);
        }
        throw new RuntimeException("查询结果为空,或者返回结果过多");
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        //使用JDK动态代理,来为dao接口生成代理对象,并返回
        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            /**
             *
             * @param o         当前代理对象的应用
             * @param method    当前被调用方法的引用
             * @param args   传递的参数
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object o, Method method, Object[] args) throws Throwable {
                //底层还是去执行JDBC代码
                //根据不同情况,来调用selectList或者selectOne

                //1.准备参数  statementId : sql 语句的唯一标识: namespace.id=接口全限定名.方法名
                    //1.1方法名
                String methodName = method.getName();
                    //1.2接口全限定名
                String className = method.getDeclaringClass().getName();
                String statementId = className+"."+methodName;
                //参数2  params : args
                    //获取被调用方法的返回值类型
                Type genericReturnType = method.getGenericReturnType();
                //判断是否进行了 泛型类型参数化(是不是有泛型   有泛型是集合) (粗略验证)
                if (genericReturnType instanceof  ParameterizedType){
                    List<Object> list = selectList(statementId, args);
                    return list;
                }


                //添加
                if (methodName.equals("addUser")){
                     addOne(statementId,args);
                     return null;
                }
                //修改
                if (methodName.equals("updateUserById")){
                    update(statementId,args);
                    return null;
                }
                //删除

                if (methodName.equals("delUserById")){
                    delete(statementId,args);
                    return null;
                }

                return selectOne(statementId,args);

            }
        });
        return (T) proxyInstance;
    }

    @Override
public void addOne(String statementid, Object... params) throws Exception {
    SimpleExecutor executor = new SimpleExecutor();
    executor.addOne(configuration, configuration.getMap().get(statementid), params);
}

    @Override
    public void update(String statementid, Object... params) throws Exception {
        SimpleExecutor executor = new SimpleExecutor();
        executor.update(configuration, configuration.getMap().get(statementid), params);
    }

    @Override
    public void delete(String statementid, Object... params) throws Exception {
        SimpleExecutor executor = new SimpleExecutor();
        executor.delete(configuration, configuration.getMap().get(statementid), params);
    }
}
